/*****************************************************************************
文 件 名: work.c
描    述: DTU工作模块
作    者: 武玉峰
版    本: 1.0
完成日期: 2016.10.31 
修改历史: 
*****************************************************************************/
#ifdef MULTI_POLE_1_5 

#include "stdio.h"
#include "string.h"
#include "work.h"
#include "gpio.h"
#include "gprs.h"
#include "rs485.h"
#include "delay.h"
#include "24cxx.h"
#include "timer.h"
#include "adc.h"
#include "usart.h"
#include "config.h"
#include "rtc.h"
#include "sys.h"
#include "fireware_update_extr.h"
#include "collect.h"

//modbus 重发次数
#define MODBUS_RETRY_COUNT 1

u16  _collectedValues[COLLECT_VALUE_SIZE];
    
//485口相关变量
 
extern u8  _485jsok;
extern u16 _Hoped485ByteCounts;  
 
//485接收缓冲区
extern u8 _RS485_RX_BUF[660];  	 
 
//接收到的数据长度
extern u8 _RS485_RX_CNT;

extern Config _Config;
extern u8         _SignalIntensity;
extern u16       _Hoped485ByteCounts ;
extern u16      _TimeOutCount; 
/*************************************************
函数名称: EnergySavingSwitch
功    能: 节能开关
参    数: flag:0 关闭 1打开          
返 回 值: 无
*************************************************/
void EnergySavingSwitch(u8 flag)
{

     if(flag==1)
 			 RELAY=1;
 		else
 			 RELAY=0;
    
}

 
  


 
/*************************************************
函数名称: GetSoilTemp
功    能: 用modbus功能码3读取土温数据
参    数: address:土温传感器地址
          databuffer：存放采集结果数据缓冲区的地址
返 回 值: 是否成功
*************************************************/
s16 GetSoilTemp(u16 *databuffer, u8 address)
{
    int k = 0;
    int j = 0;
 
    u8   ModbusCommand[8] = {0};

StartCollect:
    _Hoped485ByteCounts = 7;
    _485jsok = 0;
    BuildModbusMessage(address, 3, 0, 1, ModbusCommand);
    DebugOut("send func 3\r\n");
    CONLED = 0;
    memset(_RS485_RX_BUF, '\0', sizeof(_RS485_RX_BUF));
    _RS485_RX_CNT = 0;
    RS485_Send_Data(ModbusCommand, 8); //发送功能码3命令
    _TimeOutCount = 0;
    while(_485jsok == 0)
    {
        IWDG_Feed();
        //if(_WorkPattern == 1)return -1;
        if(_TimeOutCount > 10)
            break;

    }
    CONLED = 1;
    //数据采集成功
    if(_485jsok == 1)
    {
        DebugOut("func 3 sucess\r\n");
        j = 0;
        databuffer[0] = (_RS485_RX_BUF[3+2*j] << 8) + _RS485_RX_BUF[3+2*j+1];
 
    }
    else
    {
        DebugOut("func 3 Fail\r\n");
        DelayHalfSecond(4);
        k++;
        if(k <= MODBUS_RETRY_COUNT)
            goto StartCollect;

    }
    DelayHalfSecond(10);
    if(k > MODBUS_RETRY_COUNT)
        return 0;
    else
        return 1;


}


/*************************************************
函数名称: GetFrequencyByID
功    能: 采集铜环数据高频是水分数据，低频是盐分数据
参    数:  
          level:铜环所在层，杆上铜环从上到下的顺序从0开始。
          f：当前采集的是高频还是低频  1：低频 0：高频
返 回 值: 是否成功
*************************************************/
void SetFrequencyAndLevel(u8 address,u8 level, u8 f)
{


    u8   ModbusCommand[8] = {0};
 
    u8 k;
  
    //采集下位机的数据
    memset(_RS485_RX_BUF, 0, sizeof(_RS485_RX_BUF));


 
    k = 0;
SetLevel:
    //设置铜环Level
    _Hoped485ByteCounts = 8;
    _485jsok = 0;
    BuildModbusMessage(address, 6, 1, level, ModbusCommand);
    DebugOut("%X:send func 6:SetID\r\n",address);
    CONLED = 0;
    _RS485_RX_CNT = 0;
    RS485_Send_Data(ModbusCommand, 8); //发送功能码6命令
    DelayHalfSecond(10);
    CONLED = 1;
    if(_485jsok == 1)
    {
        DebugOut("func 6 sucess\r\n");
        //发送到232口
        DebugOut("%d %d %d %d %d %d %d %d \r\n", _RS485_RX_BUF[0], _RS485_RX_BUF[1], _RS485_RX_BUF[2], _RS485_RX_BUF[3],
                _RS485_RX_BUF[4], _RS485_RX_BUF[5], _RS485_RX_BUF[6], _RS485_RX_BUF[7]);
    }
    else
    {
        DebugOut("func 6 Fail\r\n");
        DelayHalfSecond(4);
        k++;
        if(k <= 1)
            goto SetLevel;


    }

    //设置铜环ID为15使铜环节能
   //if(id == 15)return 0;

    _TimeOutCount = 0;
   DelayHalfSecond(3);



    k = 0;
SetFrequency:
    //设置高频或低频
    _Hoped485ByteCounts = 8;
    _485jsok = 0;
    _RS485_RX_CNT = 0;
    BuildModbusMessage(address, 6, 2, f, ModbusCommand);
    if(f == 0)
    {
			DebugOut("%X:send func 6:SetHF\r\n",address);
    }
    else
    {
        DebugOut("send func 6:SetLF\r\n");
    }

    CONLED = 0;
    RS485_Send_Data(ModbusCommand, 8); //发送功能码6命令
		_TimeOutCount=0;
    while(_485jsok == 0)
    {
        IWDG_Feed();
        //if(_WorkPattern == 1)return -1;
        if(_TimeOutCount > 10)
            break;

    }
    CONLED = 1;
    if(_485jsok == 1)
    {
        DebugOut("func 6 sucess\r\n");
        //发送到232口
        DebugOut("%d %d %d %d %d %d %d %d \r\n", _RS485_RX_BUF[0], _RS485_RX_BUF[1], _RS485_RX_BUF[2], _RS485_RX_BUF[3],
              _RS485_RX_BUF[4], _RS485_RX_BUF[5], _RS485_RX_BUF[6], _RS485_RX_BUF[7]);
    }
    else
    {
        DebugOut("func 6 Fail\r\n");
        DelayHalfSecond(4);
        k++;
        if(k <= 1)
            goto SetFrequency;
    } 
}

/*************************************************
函数名称: GetFrequencyByAddress
功    能: 采集铜环数据高频是水分数据，低频是盐分数据
参    数:  address 铜环（杆）的地址
          要采集的层和高低频，必须先由SetFrequencyAndID设置好
返 回 值: 是否成功
*************************************************/
s16 GetFrequencyByAddress(u8 address)
{
    u8   ModbusCommand[8] = {0};
 
    u8 k;
    u16 value = 0;
    //采集下位机的数据
    memset(_RS485_RX_BUF, 0, sizeof(_RS485_RX_BUF));


 
    k = 0;
  

GetFrequency:
        //if(_WorkPattern == 1)return -1;
        _Hoped485ByteCounts = 7;
        _485jsok = 0;
        BuildModbusMessage(address, 3, 3, 1, ModbusCommand);
		DebugOut("%X:send func 3\r\n",address);
        CONLED = 0;
        memset(_RS485_RX_BUF, 0, sizeof(_RS485_RX_BUF));
        _RS485_RX_CNT = 0;
        RS485_Send_Data(ModbusCommand, 8); //发送功能码6
         _TimeOutCount = 0;
        while(_485jsok == 0)
        {
            IWDG_Feed();
            
            if(_TimeOutCount > 5)
                break;

        }
        CONLED = 1;
      
        //数据采集成功
        if(_485jsok == 1)
        {
            DebugOut("func 3 sucess\r\n");

            DebugOut("%d %d %d %d %d %d %d \r\n", _RS485_RX_BUF[0], _RS485_RX_BUF[1], _RS485_RX_BUF[2], _RS485_RX_BUF[3],
                    _RS485_RX_BUF[4], _RS485_RX_BUF[5], _RS485_RX_BUF[6] );
            value =   (_RS485_RX_BUF[3] << 8) + _RS485_RX_BUF[4];
        }
        else
        {
            DebugOut("func 3 Fail\r\n");
						_TimeOutCount = 0;
						while(1)
						{
							IWDG_Feed();           
							if(_TimeOutCount > 5)
									break;
						}
						k++;
						if(k <= 1)
							goto GetFrequency;
        }
        DelayHalfSecond(2);
    //}
    return value;
}
/*************************************************
函数名称: CollectData
功    能: 采集铜环、土温、电压数据，并把结果放入全局变量_collectedValues中
参    数: 无
返 回 值: 无
*************************************************/
void CollectData()
{
          
	         u8 levelId; //层
	         u8 poleId;  //杆
	       
            memset(_collectedValues, 0, sizeof(_collectedValues));	//采集缓存清零
            NETLED = 1;
	          
	         
							
	           //打开传感器总开关
							DebugOut("relay1 on\r\n");
		         RELAY1=1;
						DelayHalfSecond(6);
	          
			
						 
		 
						DebugOut("Collect Coppering!\r\n");
            //开始采集铜环 每次一层
            for(levelId = 0; levelId < 8; ++levelId)
            {
							 	DebugOut("\r\ncollect level %d HF\r\n", levelId + 1);
							  //水分为高频值 
							  for(poleId=0;poleId<8;++poleId)
	              { //设置层和高频								
									    if(_Config._HighFreqConfig[poleId] & (1 << levelId))
											{
												SetFrequencyAndLevel(_Config._CopperRingAddress[poleId], levelId, 0); 
											}
							  }
								//延时10秒
                DelayHalfSecond(20); 
									 
							  for(poleId=0;poleId<8;++poleId)
	              { 
									if(_Config._HighFreqConfig[poleId] & (1 << levelId))
									{
									//开始采集
									  _collectedValues[levelId*16+poleId] =GetFrequencyByAddress(_Config._CopperRingAddress[poleId]); 
									}
							  }
								
								
								
								
							  DebugOut("\r\ncollect level %d LF\r\n",levelId + 1);
								//盐分为低频值， 高频为0，低频为1
							  for(poleId=0;poleId<8;++poleId)
	              { 	
									if(_Config._LowFreqConfig[poleId] & (1 << levelId))
									{
									//设置层和低频													
										 SetFrequencyAndLevel(_Config._CopperRingAddress[poleId], levelId, 1); 
									}
							  }
								
								//延时5秒
                DelayHalfSecond(10); 
								for(poleId=0;poleId<8;++poleId)
	              {     
									  if(_Config._LowFreqConfig[poleId] & (1 << levelId))
									{
									//开始采集
								    _collectedValues[levelId*16+poleId+8]=  GetFrequencyByAddress(_Config._CopperRingAddress[poleId]); 
									}
							  }
            }
						
								//开始采集8个土温 每次一杆
	        for(poleId=0;poleId<8;++poleId)
	        { 
					
						DebugOut("Collect Soil Temperature:P%d!\r\n",poleId);
            //采集土温
            for(levelId = 0; levelId < 8; ++levelId)
            {
                IWDG_Feed();
                if(_Config._SoilTempConfig[poleId] & (1 << levelId))
                {
                    DebugOut("\r\ncollect soil temp data level %d\r\n", levelId + 1);
                    GetSoilTemp(&_collectedValues[128+poleId*8+levelId], _Config._SoilTempAddress[poleId][levelId]);  
                }
            }
					}
						
							 //关闭传感器总开关
						DebugOut("relay1 off\r\n");
						 RELAY1=0; 

             //信号强度
						_collectedValues[192] = _SignalIntensity;  
}

#endif
